package com.lingjtx.im.core.config;

import com.lingjtx.common.core.constant.MqConst;
import com.lingjtx.common.redis.config.ServerNodeConfig;
import com.lingjtx.common.thread.config.ObjectPoolTemplateConfig;
import com.lingjtx.common.thread.mq.FastJsonAutoTypeMessageConverter;
import com.lingjtx.common.thread.mq.RabbitSenderTemplate;
import com.lingjtx.common.thread.pooling.ObjectFactory;
import com.lingjtx.common.thread.pooling.ObjectPoolTemplate;
import com.lingjtx.common.thread.pooling.RabbitTemplateFactory;
import jakarta.annotation.PostConstruct;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

@Configuration
public class RabbitMQConfig {

    private final AmqpAdmin rabbitAdmin;
    private final ServerNodeConfig serverNodeConfig;

    public RabbitMQConfig(AmqpAdmin rabbitAdmin, ServerNodeConfig serverNodeConfig) {
        this.rabbitAdmin = rabbitAdmin;
        this.serverNodeConfig = serverNodeConfig;
    }

    @PostConstruct
    public void declareNodeQueue() {
        // 主队列绑定
        Queue mainQueue = new Queue(MqConst.IM_QUEUE_MAIN, true);
        Binding mainBinding = BindingBuilder.bind(mainQueue)
                .to(new TopicExchange(MqConst.IM_EXCHANGE_NAME))
                .with(MqConst.IM_ROUTING_MAIN_KEY + serverNodeConfig.getNodeId());
        rabbitAdmin.declareQueue(mainQueue);
        rabbitAdmin.declareBinding(mainBinding);

        // 节点服务队列绑定
        Queue queue = new Queue(MqConst.IM_QUEUE_NODE + serverNodeConfig.getNodeId(), true);
        Binding binding = BindingBuilder.bind(queue)
                .to(new TopicExchange(MqConst.IM_EXCHANGE_NAME))
                .with(MqConst.IM_ROUTING_NODE_KEY + serverNodeConfig.getNodeId());
        rabbitAdmin.declareQueue(queue);
        rabbitAdmin.declareBinding(binding);
    }

    @Bean("dynamicImQueue")
    public String dynamicImQueue() {
        return MqConst.IM_QUEUE_NODE + serverNodeConfig.getNodeId();
    }

    @Bean
    public FastJsonAutoTypeMessageConverter fastJsonAutoTypeMessageConverter() {
        List<String> whitelistPackages = List.of("com.lingjtx.common.core.model.mq");
        return new FastJsonAutoTypeMessageConverter(whitelistPackages);
    }

    @Bean("rabbitObjectPoolTemplate")
    public ObjectPoolTemplate<RabbitTemplate> rabbitObjectPoolTemplate(ObjectPoolTemplateConfig config,
                                                                       CachingConnectionFactory rabbitConnectionFactory,
                                                                       FastJsonAutoTypeMessageConverter converter) {
        ObjectFactory<RabbitTemplate> rabbitTemplateObjectFactory = new RabbitTemplateFactory(config.getThreadPoolManager(),
                rabbitConnectionFactory, converter);
        return config.buildTemplate("rabbit", rabbitTemplateObjectFactory);
    }

    @Bean
    public RabbitSenderTemplate rabbitSenderTemplate(@Qualifier("rabbitObjectPoolTemplate") ObjectPoolTemplate<RabbitTemplate> rabbitPool) {
        return new RabbitSenderTemplate(rabbitPool);
    }
}
